package link.jfire.simplerpc.server;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import link.jfire.baseutil.simplelog.ConsoleLogFactory;
import link.jfire.baseutil.simplelog.Logger;
import link.jfire.core.JfireContext;
import link.jfire.simplerpc.server.messagehandler.InfoMessageHandler;
import link.jfire.simplerpc.server.messagehandler.InvokeMessageHandler;
import link.jfire.socket.socketserver.transfer.server.ServerMain;
import sun.reflect.MethodAccessor;

@SuppressWarnings("restriction")
public class RcServer
{
    protected ServerMain    serverMain;
    protected Logger        logger = ConsoleLogFactory.getLogger();
    protected static Method acquireMethodAccessor;
    protected static Field  methodAccessor;
    
    static
    {
        try
        {
            acquireMethodAccessor = Method.class.getDeclaredMethod("acquireMethodAccessor");
            acquireMethodAccessor.setAccessible(true);
            methodAccessor = Method.class.getDeclaredField("methodAccessor");
            methodAccessor.setAccessible(true);
        }
        catch (NoSuchMethodException | SecurityException | NoSuchFieldException e)
        {
            e.printStackTrace();
        }
    }
    
    protected RcServer()
    {
    
    }
    
    /**
     * 以服务器配置文件类以及代理名称以及实例初始化远程调用服务器
     * 
     * @param port
     * @param impl
     */
    public RcServer(RcConfig rcConfig)
    {
        if (rcConfig.isParamOk() == false)
        {
            throw new RuntimeException("请检查代理名称和实现数组是否正常");
        }
        rcConfig.addPackageNames("link.jfire.simplerpc.server.messagehandler");
        serverMain = new ServerMain(rcConfig);
        bind(rcConfig.getProxyNames(), rcConfig.getImpls(), serverMain.getContext());
    }
    
    protected void bind(String[] proxyNames, Object[] impls, JfireContext context)
    {
        InvokeMessageHandler invokeMessageHandler = context.getBean(InvokeMessageHandler.class);
        Map<String, MethodAccessor>[] methodNames = initMethodMap(impls);
        invokeMessageHandler.setWorkUnit(proxyNames, impls, methodNames);
        InfoMessageHandler infoMessageHandler = context.getBean(InfoMessageHandler.class);
        infoMessageHandler.setWorkUnit(proxyNames, impls);
    }
    
    private Map<String, MethodAccessor>[] initMethodMap(Object[] impls)
    {
        @SuppressWarnings("unchecked")
        Map<String, MethodAccessor>[] methodNames = new HashMap[impls.length];
        for (int i = 0; i < impls.length; i++)
        {
            methodNames[i] = new HashMap<String, MethodAccessor>();
            Method[] methods = impls[i].getClass().getDeclaredMethods();
            for (Method each : methods)
            {
                // 必须设置成true，这样调用效率最高。额外开销约等于直接调用。也就是总计调用耗时是原本的2倍
                each.setAccessible(true);
                methodNames[i].put(each.getName(), fastMethod(each));
            }
        }
        return methodNames;
        
    }
    
    /**
     * 获取method的更快的执行者MethodAccessor
     * 
     * @param src
     * @return
     */
    private MethodAccessor fastMethod(Method src)
    {
        try
        {
            acquireMethodAccessor.invoke(src);
            return (MethodAccessor) methodAccessor.get(src);
        }
        catch (SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
        {
            e.printStackTrace();
        }
        return null;
    }
    
    public void start()
    {
        serverMain.start();
    }
    
    public void stop()
    {
        serverMain.stop();
    }
    
}
